package estimators.numberoOfDocuments;

import java.util.ArrayList;
import java.util.Hashtable;

import distributedRE.model.DataBase;
import distributedRE.model.QueryDatabase;

public class DirichletPriorSmoothedEstimator extends NumberOfDocumentCalculator {

	private long global_size;
	private ArrayList<DataBase> databases;
	private double smoother;
	private Hashtable<String, Long> cache;

	public DirichletPriorSmoothedEstimator(ArrayList<DataBase> databases, double smoother){
		
		global_size = -1;
	
		this.databases = databases;
		
		this.smoother = smoother;
		
		cache = new Hashtable<String, Long>();
		
	}
	
	@Override
	protected double getMustNotProbability(String term, QueryDatabase qdb) {
		
		double frequency = (double)qdb.getFrequency(term,false);
		
		double global_probability = ((double)getGlobalSize() - (double)getGlobalWordFrequency(term)) / (double) getGlobalSize();
		
		double size = (double)qdb.getNumberOfDocuments();
		
		return (size - frequency + smoother*global_probability)/(size + smoother);
	}

	@Override
	protected double getMustProbability(String term, QueryDatabase qdb) {
		
		double frequency = (double)qdb.getFrequency(term,true);
		
		double global_probability = (double) getGlobalWordFrequency(term) / (double) getGlobalSize();
		
		double size = (double)qdb.getNumberOfDocuments();
		
		return (frequency + smoother*global_probability)/(size + smoother);
		
		
	}

	private long getGlobalSize(){
		
		if (global_size==-1){
			
			global_size = 0;
			
			for (DataBase database : databases) {
				
				global_size += database.getNumberOfDocuments();
				
			}
			
		}
		
		return global_size;
	}
	
	private long getGlobalWordFrequency(String term){
		
		Long ret = cache.get(term);
		
		if (ret == null){
			
			long aux = 0;
			
			for (DataBase database : databases) {
				
				aux += database.getFrequency(term);
				
			}
			
			ret = new Long(aux);
			
			cache.put(term, ret);
			
		}
		
		return ret.longValue();
		
	}
	
	public String toString(){
		return "Dirichlet Prior Smoothing with an smoother value of: " + smoother;
	}
	
}
